"""# 谜题训练场开发任务

## 任务概述
你是一位资深程序员，我需要你帮我实现一个特定谜题的训练场环境类。这个类继承自`Basebootcamp`，用于生成谜题实例并验证解答。

## 背景说明
我正在开发一系列谜题训练场，每个训练场对应一个特定类型的谜题。训练场类命名为`{PuzzleName}bootcamp`，其中`PuzzleName`是谜题的名称。

每个训练场类主要提供两个核心功能：
1. 生成该谜题类型的问题实例
2. 验证用户对问题的回答是否正确

## 技术接口规范

### 类方法实现要求

```python
from bootcamp import Basebootcamp

class {PuzzleName}bootcamp(Basebootcamp):
    def __init__(self, **params):
        \"\"\"
        请你自定义params，以保存该puzzle相关的参数，例如网格大小等，参数配有默认值
        \"\"\"
        pass
    
    def case_generator(self):
        \"\"\"
        生成谜题实例，提示：为保证谜题有解，可以先生成结果再对结果处理得到谜题
        返回：一个可JSON序列化的字典（避免包含set等无法通过json.dumps处理的数据结构）
        \"\"\"
        pass
    
    @staticmethod
    def prompt_func(question_case) -> str:
        \"\"\"
        将case_generator生成的谜题实例转换为文本形式的问题，问题中包含问题背景、对谜题规则的介绍、具体要解决的谜题实例、期望最终答案的格式，
        例如：你是xxxx，请你解答yyyy，规则如下：yyyy，最终答案放置在：zzzzz
        注意：请参照提供的谜题描述进行复述，规则应当描述详细，包括任务背景、具体任务操作规则、对题目格式和答案格式的含义介绍等，

        参数:
            question_case: 由case_generator生成的谜题实例
            
        返回:
            str: 格式化的问题字符串
            
        注意:
            1. 需考虑问题的格式，以便后续能正确提取
            2. 问题描述中应包含期望的答案格式说明，以便后续能正确提取，为了避免抽取时匹配出干扰项，请要求模型将答案放在特定标签（如双括号）内，例如[[your answer here]]
        \"\"\"
        pass
    
    @staticmethod
    def extract_output(output):
        \"\"\"
        从LLM的回复中提取符合格式要求的答案，如有多个，请抽取最后一个，避免使用re.search等只抽取第一个结果的方式。
        
        参数:
            output: LLM的完整输出（包含原始问题和回答）
            
        返回:
            提取的答案，若未找到符合格式的答案则返回None
        \"\"\"
        pass
    
    @classmethod
    def _verify_correction(cls, solution, identity):
        \"\"\"
        验证提取的答案是否正确，注意一个问题可以能有多个解，按照谜题规则进行检验，不要直接匹配可能的答案。
        
        参数:
            solution: extract_output提取的答案
            identity: case_generator生成的谜题实例
            
        返回:
            bool: 答案是否正确
        \"\"\"
        pass
```

### 验证评分方法（基类已实现）

```python
@classmethod
def verify_score(cls, model_output, identity:dict, format_score=0.1) -> float:
    \"\"\"
    验证输出结果并评分。
    
    参数:
        model_output: 模型的完整输出
        identity: 谜题实例（由case_generator生成）
        format_score: 答案格式正确时的基础分数
    
    返回:
        float: 评分结果（0-1之间）
    \"\"\"
    score = 0. 
    try:
        extract_solution = cls.extract_output(model_output)
        if extract_solution is None:
            return score
        else:
            score = format_score # 格式正确时的基础分数
        if cls._verify_correction(extract_solution, identity):
            score = 1.  # 答案完全正确时的满分
    except Exception as e:
        # 处理异常情况
        pass
    return score
```

### 使用示例

```python
# 初始化谜题训练场
bootcamp = Puzzlebootcamp()

# 生成谜题实例
case = bootcamp.case_generator()

# 将谜题转换为文本问题
prompt = Puzzlebootcamp.prompt_func(case)

# 获取LLM对问题的解答
response = get_response(prompt, \"LLM\")

# 从完整对话中提取答案
extracted_output = Puzzlebootcamp.extract_output(prompt + response)

# 验证答案并评分
score = Puzzlebootcamp.verify_score(extracted_output, case)
```

## 你的任务
请根据以下谜题描述（谜题描述可能不完整，请先结合你的知识澄清规则），实现一个完整的谜题训练场类：

### 谜题描述
a◎b=(a + bi)^2Example questions are as follows:

<example 0>
Compute (4◎5)+(2◎3).
If the answer is a complex number, write it in the form x + yi.
The answer may be negative, if so write it in a format such as '-5'.
Please wrap the answer in double square brackets, like this: [[your answer]].
</example 0>

<example 1>
Compute (2◎3)−(2◎2).
If the answer is a complex number, write it in the form x + yi.
The answer may be negative, if so write it in a format such as '-5'.
Please wrap the answer in double square brackets, like this: [[your answer]].
</example 1>

<example 2>
Compute (1◎1)×(2◎2).
The answer may be negative, if so write it in a format such as '-5'.
Please wrap the answer in double square brackets, like this: [[your answer]].
</example 2>

<example 3>
Compute (4◎5)×(2◎3).
If the answer is a complex number, write it in the form x + yi.
The answer may be negative, if so write it in a format such as '-5'.
Please wrap the answer in double square brackets, like this: [[your answer]].
</example 3>

<example 4>
Compute (2◎3)+(1◎4).
If the answer is a complex number, write it in the form x + yi.
The answer may be negative, if so write it in a format such as '-5'.
Please wrap the answer in double square brackets, like this: [[your answer]].
</example 4>

<example 5>
Compute (1◎2)+(3◎1).
If the answer is a complex number, write it in the form x + yi.
The answer may be negative, if so write it in a format such as '-5'.
Please wrap the answer in double square brackets, like this: [[your answer]].
</example 5>

<example 6>
If (X◎2)+(1◎3)=4+22i, find X.
The answer should only be given as a number.
Please wrap the answer in double square brackets, like this: [[your answer]].
</example 6>

<example 7>
If (3◎Y)−(2◎1)=5+2i, find Y.
The answer should only be given as a number.
Please wrap the answer in double square brackets, like this: [[your answer]].
</example 7>

<example 8>
If (2◎3)+(1◎X)=−8+16i, find X.
The answer should only be given as a number.
Please wrap the answer in double square brackets, like this: [[your answer]].
</example 8>

<example 9>
If (6◎3)+(X◎2)×2=37+60i, find X.
The answer should only be given as a number.
Please wrap the answer in double square brackets, like this: [[your answer]].
</example 9>


请完成上述谜题的训练场环境类实现，包括所有必要的方法。
"""

from bootcamp import Basebootcamp
import random
import re
from bootcamp import Basebootcamp

class KorOperationUnicode25cebootcamp(Basebootcamp):
    def __init__(self, min_val=-10, max_val=10, equation_prob=0.4):
        self.min_val = min_val
        self.max_val = max_val
        self.equation_prob = equation_prob
        self.operators = ['+', '-', '*']
    
    @staticmethod
    def compute_operator(a, b):
        """计算a◎b对应的复数平方"""
        return (a**2 - b**2, 2*a*b)
    
    def _generate_equation_case(self):
        """生成包含多种形式的方程"""
        equation_type = random.choice([
            'basic_left', 
            'basic_right',
            'scalar_left',
            'scalar_right'
        ])
        
        X = random.randint(self.min_val, self.max_val)
        a = random.randint(1, 5)  # 避免a为0导致多解
        b = random.randint(self.min_val, self.max_val)
        c = random.randint(self.min_val, self.max_val)
        k = random.randint(2, 5)
        
        if equation_type.startswith('basic'):
            term1_real, term1_imag = self.compute_operator(X, a)
            term2_real, term2_imag = self.compute_operator(b, c)
            op = '+' if random.random() < 0.5 else '-'
            
            if equation_type == 'basic_left':
                # (X◎a) ± (b◎c) = target
                target_real = term1_real + term2_real if op == '+' else term1_real - term2_real
                target_imag = term1_imag + term2_imag if op == '+' else term1_imag - term2_imag
                return {
                    'type': 'equation',
                    'form': f'(X◎{a}) {op} ({b}◎{c})',
                    'x_pos': 'left',
                    'params': (a, b, c, op),
                    'target': (target_real, target_imag)
                }
            else:  # basic_right
                # (b◎c) ± (X◎a) = target
                target_real = term2_real + term1_real if op == '+' else term2_real - term1_real
                target_imag = term2_imag + term1_imag if op == '+' else term2_imag - term1_imag
                return {
                    'type': 'equation',
                    'form': f'({b}◎{c}) {op} (X◎{a})',
                    'x_pos': 'right',
                    'params': (a, b, c, op),
                    'target': (target_real, target_imag)
                }
        
        else:  # scalar类型
            scalar = k
            if equation_type == 'scalar_left':
                # (X◎a) ± k×(b◎c) = target
                term1_real, term1_imag = self.compute_operator(X, a)
                term2_real, term2_imag = self.compute_operator(b, c)
                term2_real *= scalar
                term2_imag *= scalar
                op = '+' if random.random() < 0.5 else '-'
                
                target_real = term1_real + term2_real if op == '+' else term1_real - term2_real
                target_imag = term1_imag + term2_imag if op == '+' else term1_imag - term2_imag
                return {
                    'type': 'equation',
                    'form': f'(X◎{a}) {op} {scalar}×({b}◎{c})',
                    'x_pos': 'left_scalar',
                    'params': (a, b, c, scalar, op),
                    'target': (target_real, target_imag)
                }
            else:  # scalar_right
                # k×(X◎a) ± (b◎c) = target
                term1_real, term1_imag = self.compute_operator(X, a)
                term1_real *= scalar
                term1_imag *= scalar
                term2_real, term2_imag = self.compute_operator(b, c)
                op = '+' if random.random() < 0.5 else '-'
                
                target_real = term1_real + term2_real if op == '+' else term1_real - term2_real
                target_imag = term1_imag + term2_imag if op == '+' else term1_imag - term2_imag
                return {
                    'type': 'equation',
                    'form': f'{scalar}×(X◎{a}) {op} ({b}◎{c})',
                    'x_pos': 'right_scalar',
                    'params': (a, b, c, scalar, op),
                    'target': (target_real, target_imag)
                }
    
    def case_generator(self):
        if random.random() < self.equation_prob:
            return self._generate_equation_case()
        else:
            op = random.choice(self.operators)
            terms = [
                (random.randint(self.min_val, self.max_val), 
                 random.randint(self.min_val, self.max_val))
                for _ in range(2)
            ]
            res1 = self.compute_operator(*terms[0])
            res2 = self.compute_operator(*terms[1])
            
            if op == '+':
                real = res1[0] + res2[0]
                imag = res1[1] + res2[1]
            elif op == '-':
                real = res1[0] - res2[0]
                imag = res1[1] - res2[1]
            else:
                real = res1[0]*res2[0] - res1[1]*res2[1]
                imag = res1[0]*res2[1] + res1[1]*res2[0]
            
            return {
                'type': 'calculation',
                'terms': terms,
                'operator': op,
                'correct': (real, imag)
            }
    
    @staticmethod
    def prompt_func(question_case):
        if question_case['type'] == 'calculation':
            (a1, b1), (a2, b2) = question_case['terms']
            op_map = {'+': '+', '-': '-', '*': '×'}
            return (
                "Define: a◎b=(a + bi)^2"
                f"Compute ({a1}◎{b1}) {op_map[question_case['operator']]} ({a2}◎{b2}).\n"
                "Format: x + yi (e.g. '3-4i', '-5')\n"
                "Put your answer within [[ ]]"
            )
        else:
            return (
                "Define: a◎b=(a + bi)^2"
                f"If {question_case['form']} = {question_case['target'][0]} + {question_case['target'][1]}i\n"
                "Find X (integer only). Wrap answer in [[ ]]"
            )
    
    @staticmethod
    def extract_output(output):
        matches = re.findall(r'\[\[([^\[\]]+)\]\]', output)
        return matches[-1].strip() if matches else None
    
    @classmethod
    def _verify_correction(cls, solution, identity):
        try:
            if identity['type'] == 'calculation':
                real, imag = cls.parse_complex(solution)
                return real == identity['correct'][0] and imag == identity['correct'][1]
            else:
                X = int(solution)
                params = identity['params']
                
                if identity['x_pos'] == 'left':
                    a, b, c, op = params
                    left_real, left_imag = cls.compute_operator(X, a)
                    right_real, right_imag = cls.compute_operator(b, c)
                elif identity['x_pos'] == 'right':
                    a, b, c, op = params
                    right_real, right_imag = cls.compute_operator(X, a)
                    left_real, left_imag = cls.compute_operator(b, c)
                elif identity['x_pos'] == 'left_scalar':
                    a, b, c, scalar, op = params
                    left_real, left_imag = cls.compute_operator(X, a)
                    right_real, right_imag = cls.compute_operator(b, c)
                    right_real *= scalar
                    right_imag *= scalar
                elif identity['x_pos'] == 'right_scalar':
                    a, b, c, scalar, op = params
                    right_real, right_imag = cls.compute_operator(X, a)
                    right_real *= scalar
                    right_imag *= scalar
                    left_real, left_imag = cls.compute_operator(b, c)
                
                if identity.get('form', '').split()[1] == '+':
                    total_real = left_real + right_real
                    total_imag = left_imag + right_imag
                else:
                    total_real = left_real - right_real
                    total_imag = left_imag - right_imag
                
                return (total_real == identity['target'][0] and 
                        total_imag == identity['target'][1])
        except:
            return False
    
    @staticmethod
    def parse_complex(s):
        s = s.replace(' ', '').lower().replace('i', 'j').rstrip('j')
        try:
            c = complex(s)
            return (int(c.real), int(c.imag))
        except:
            if s:
                return (int(s), 0)
            return (0, 0)
